package com.znfeiche.server.core;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.znfeiche.common.ServletRequest;
import com.znfeiche.common.ServletResponse;
import com.znfeiche.exception.BusinessException;
import com.znfeiche.exception.EmBusinessError;
import com.znfeiche.server.common.Handler;
import com.znfeiche.server.common.HandlerMapping;
import com.znfeiche.server.common.ViewResolver;

/**
 *  控制器
 *  	a.负责接收请求(.do结尾的请求),然后依据
 *  	HandlerMapping的配置，调用对应的处理器
 *  	(比如HelloController)来处理该请求。
 *  	b.将处理器的返回结果交给视图解析器(ViewResolver)
 *  	来解析，然后调用对应的视图来展现处理结果。
 */
public class DispatcherServlet implements Servlet {
	private static final long serialVersionUID = 1L;

	private HandlerMapping handlerMapping;
	
	private ViewResolver viewResolver;
	
	@Override
	public void init() throws BusinessException {
		/*
		 * 读取配置文件(smartmvc.xml)的内容,
		 * 然后将这些类(即处理器)实例化。接下来，
		 * 将这些处理器实例放到一个集合里面，然后
		 * 将这个集合交给HandlerMapping来处理。
		 */
		//读取初始化参数，获得配置文件名
		String fileName = getServletConfig()
				.getInitParameter("configLocation");
		
		//使用Dom4j解析xml文件
		SAXReader reader = new SAXReader();
		InputStream in = 
				getClass().getClassLoader()
				.getResourceAsStream(fileName);
		try {
			//读取xml文件，在内存当中创建一棵树
			Document doc = reader.read(in);
			//获得根节点
			Element root  = doc.getRootElement();
			//找到根节点下面的所有的子节点
			List<Element> eles = 
						root.elements();
			
			List beans = new ArrayList();
			
			//读取子节点的class属性值
			for(Element ele: eles){
				String className = 
						ele.attributeValue("class");
				System.out.println("className:" 
						+ className);
				//利用java反射，将类实例化
				Object obj = Class.forName(
						className).newInstance();
				//指这些实例(即处理器)添加到集合里面
				beans.add(obj);
			}
			
			System.out.println("beans:" + beans);
			
			//将集合(包含有处理器)交给HandlerMapping
			//来处理。
			handlerMapping = new HandlerMapping();
			handlerMapping.process(beans);
			
			//创建ViewResolver实例
			viewResolver = new ViewResolver();
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new BusinessException(EmBusinessError.UNKNOWN_ERROR);
		}
	}

	public void service(
			ServletRequest request,
			ServletResponse response) 
					throws BusinessException{
		//获得请求资源路径
		String uri = request.getRequestURI();
		System.out.println("uri:" + uri);
		
		//获得应用名
		String contextPath = 
				request.getContextPath();
		System.out.println("contextPath:"
				+ contextPath);
		
		//截取请求资源路径的一部分(请求路径)，方便比较
		String path = uri.substring(
				contextPath.length());
		System.out.println("path:" + path);
		
		/*
		 * 依据HandlerMapping的配置，调用对应的处理器
		 * 注:
		 * 		HandlerMapping有一个方法，只需要提供
		 * 	请求路径(path),该方法会返回Handler对象(
		 * 	该对象包含执行方法所需要的Method对象和Object)。
		 */
		//获得请求路径对应的Handler对象
		Handler handler = 
				handlerMapping.getHandler(path);
		//利用Handler对象调用处理器的方法
		Method mh = handler.getMh();
		Object obj = handler.getObj();
		try {
			
			//处理器返回视图名
			Object returnVal = mh.invoke(obj);
			System.out.println("returnVal:" 
					+ returnVal);

			//调用ViewResolver来处理视图名
			viewResolver.processView(
					returnVal.toString(), 
					request, response);
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new BusinessException(EmBusinessError.UNKNOWN_ERROR);
		} 
		
		
		
	}

	

}
